package com.xy.xyaicpzs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xy.xyaicpzs.domain.entity.DltDrawRecord;
import com.xy.xyaicpzs.domain.entity.DltPredictRecord;
import com.xy.xyaicpzs.mapper.DltDrawRecordMapper;
import com.xy.xyaicpzs.mapper.DltPredictRecordMapper;
import com.xy.xyaicpzs.domain.vo.PrizeEstimateVO;
import com.xy.xyaicpzs.domain.vo.RedBallHitRateVO;
import com.xy.xyaicpzs.domain.vo.UserPredictStatVO;
import com.xy.xyaicpzs.service.DltDataAnalysisService;
import com.xy.xyaicpzs.service.DltDrawRecordService;
import com.xy.xyaicpzs.util.DltPrizeCalculator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 大乐透数据分析服务实现类
 */
@Slf4j
@Service
public class DltDataAnalysisServiceImpl implements DltDataAnalysisService {
    
    @Autowired
    private DltPredictRecordMapper dltPredictRecordMapper;

    @Autowired
    private DltDrawRecordMapper dltDrawRecordMapper;
    
    @Autowired
    private DltDrawRecordService dltDrawRecordService;
    
    @Override
    public int processPendingDltPredictions() {
        log.info("开始处理大乐透待开奖预测记录");
        
        // 查询所有待开奖的大乐透预测记录
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("predictStatus", "待开奖");
        List<DltPredictRecord> pendingRecords = dltPredictRecordMapper.selectList(queryWrapper);
        
        log.info("找到{}条待开奖的大乐透预测记录", pendingRecords.size());
        
        int processedCount = 0;
        
        for (DltPredictRecord record : pendingRecords) {
            try {
                // 查询对应期号的开奖结果
                // 注意：DltDrawRecord的drawId是String类型，DltPredictRecord的drawId是Long类型
                QueryWrapper<DltDrawRecord> drawQueryWrapper = new QueryWrapper<>();
                drawQueryWrapper.eq("drawId", String.valueOf(record.getDrawId()));
                DltDrawRecord drawRecord = dltDrawRecordMapper.selectOne(drawQueryWrapper);
                
                if (drawRecord != null) {
                    log.debug("处理预测记录ID：{}，期号：{}", record.getId(), record.getDrawId());
                    
                    // 构建预测号码数组 [前区5个号码, 后区2个号码]
                    Integer[] predictNumbers = {
                        record.getFrontendBall1(),
                        record.getFrontendBall2(),
                        record.getFrontendBall3(),
                        record.getFrontendBall4(),
                        record.getFrontendBall5(),
                        record.getBackendBall1(),
                        record.getBackendBall2()
                    };
                    
                    // 构建开奖号码数组 [前区5个号码, 后区2个号码]
                    Integer[] drawNumbers = {
                        drawRecord.getFrontBall1(),
                        drawRecord.getFrontBall2(),
                        drawRecord.getFrontBall3(),
                        drawRecord.getFrontBall4(),
                        drawRecord.getFrontBall5(),
                        drawRecord.getBackBall1(),
                        drawRecord.getBackBall2()
                    };
                    
                    // 使用DltPrizeCalculator计算中奖结果
                    DltPrizeCalculator.PrizeResult prizeResult = DltPrizeCalculator.calculatePrize(predictNumbers, drawNumbers);
                    
                    // 更新预测记录
                    // 根据中奖结果设置状态
                    if(prizeResult.getPrizeLevel().equals("未中奖")){
                        record.setPredictStatus("未中奖");
                    }else{
                        record.setPredictStatus("已中奖");
                    }
                    record.setPredictResult(prizeResult.getPrizeLevel());
                    record.setBonus(prizeResult.getBonus());
                    
                    dltPredictRecordMapper.updateById(record);
                    
                    log.debug("预测记录ID：{} 处理完成，中奖等级：{}，奖金：{}", 
                             record.getId(), prizeResult.getPrizeLevel(), prizeResult.getBonus());
                    
                    processedCount++;
                } else {
                    log.debug("未找到期号{}的开奖记录", record.getDrawId());
                }
            } catch (Exception e) {
                log.error("处理预测记录ID：{} 时发生错误：{}", record.getId(), e.getMessage(), e);
            }
        }
        
        log.info("大乐透待开奖预测记录处理完成，共处理{}条记录", processedCount);
        return processedCount;
    }
    
    @Override
    public UserPredictStatVO getUserDltPredictStat(Long userId) {
        log.info("开始获取用户{}的大乐透预测统计数据", userId);
        
        UserPredictStatVO statVO = new UserPredictStatVO();
        
        // 查询用户的所有大乐透预测记录
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        List<DltPredictRecord> predictRecords = dltPredictRecordMapper.selectList(queryWrapper);
        
        if (predictRecords == null || predictRecords.isEmpty()) {
            log.info("用户{}没有大乐透预测记录", userId);
            statVO.setUserId(userId);
            statVO.setPredictCount(0L);
            statVO.setHitCount(0L);
            statVO.setPendingCount(0L);
            statVO.setDrawnCount(0L);
            statVO.setHitRate(BigDecimal.ZERO);
            return statVO;
        }
        
        // 统计数据
        long totalPredicts = predictRecords.size();
        long hitCount = 0L;
        long pendingCount = 0L;
        long drawnCount = 0L;
        
        for (DltPredictRecord record : predictRecords) {
            if ("待开奖".equals(record.getPredictStatus())) {
                pendingCount++;
            } else if ("已开奖".equals(record.getPredictStatus())) {
                drawnCount++;
                // 检查是否中奖（除了"未中奖"都算中奖）
                if (!"未中奖".equals(record.getPredictResult()) && 
                    record.getPredictResult() != null && 
                    !record.getPredictResult().trim().isEmpty()) {
                    hitCount++;
                }
            }
        }
        
        // 计算命中率
        BigDecimal hitRate = drawnCount > 0 ? 
            BigDecimal.valueOf(hitCount).divide(BigDecimal.valueOf(drawnCount), 4, RoundingMode.HALF_UP) : 
            BigDecimal.ZERO;
        
        statVO.setUserId(userId);
        statVO.setPredictCount(totalPredicts);
        statVO.setHitCount(hitCount);
        statVO.setPendingCount(pendingCount);
        statVO.setDrawnCount(drawnCount);
        statVO.setHitRate(hitRate);
        
        log.info("用户{}大乐透预测统计数据：预测次数={}，待开奖次数={}，已开奖次数={}，命中次数={}，命中率={}", 
                userId, totalPredicts, pendingCount, drawnCount, hitCount, hitRate);
        
        return statVO;
    }
    
    @Override
    public PrizeEstimateVO getDltPrizeStatistics(Long userId, Long predictId) {
        log.info("开始为用户{}进行大乐透奖金统计，predictId={}", userId, predictId);
        
        // 查询条件
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        // 排除待开奖状态
        queryWrapper.eq("predictStatus", "已开奖");
        // 如果指定了预测记录ID，则只查询该记录
        if (predictId != null) {
            queryWrapper.eq("id", predictId);
        }
        
        // 查询用户的大乐透预测记录
        List<DltPredictRecord> records = dltPredictRecordMapper.selectList(queryWrapper);
        
        // 按中奖等级分组统计
        Map<String, Integer> countByPrizeLevel = new HashMap<>();
        Map<String, BigDecimal> totalBonusByPrizeLevel = new HashMap<>();
        
        // 初始化大乐透的所有等级
        String[] prizeLevels = {"一等奖", "二等奖", "三等奖", "四等奖", "五等奖", "六等奖", "七等奖", "八等奖", "九等奖", "未中奖"};
        for (String level : prizeLevels) {
            countByPrizeLevel.put(level, 0);
            totalBonusByPrizeLevel.put(level, BigDecimal.ZERO);
        }
        
        // 统计各等级数量和奖金
        for (DltPredictRecord record : records) {
            String prizeLevel = record.getPredictResult();
            if (prizeLevel == null || prizeLevel.trim().isEmpty()) {
                prizeLevel = "未中奖";
            }
            
            // 更新计数
            countByPrizeLevel.put(prizeLevel, countByPrizeLevel.getOrDefault(prizeLevel, 0) + 1);
            
            // 累计奖金
            if (record.getBonus() != null) {
                BigDecimal bonus = new BigDecimal(record.getBonus().toString());
                totalBonusByPrizeLevel.put(prizeLevel, 
                    totalBonusByPrizeLevel.getOrDefault(prizeLevel, BigDecimal.ZERO).add(bonus));
            }
        }
        
        // 构建返回结果
        List<PrizeEstimateVO.PrizeDetailItem> prizeDetails = new ArrayList<>();
        
        // 按顺序添加各等级的统计结果（从高到低）
        for (String level : prizeLevels) {
            // 跳过没有记录的等级
            if (countByPrizeLevel.get(level) <= 0) {
                continue;
            }
            
            int count = countByPrizeLevel.get(level);
            BigDecimal totalBonus = totalBonusByPrizeLevel.get(level);
            BigDecimal singlePrize = BigDecimal.ZERO;
            if (count > 0 && totalBonus.compareTo(BigDecimal.ZERO) > 0) {
                singlePrize = totalBonus.divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
            }
            
            prizeDetails.add(PrizeEstimateVO.PrizeDetailItem.builder()
                    .prizeLevel(level)
                    .winningCount(count)
                    .singlePrize(singlePrize)
                    .subtotal(totalBonus)
                    .build());
        }
        
        // 计算总奖金
        BigDecimal totalPrize = prizeDetails.stream()
                .map(PrizeEstimateVO.PrizeDetailItem::getSubtotal)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        PrizeEstimateVO result = PrizeEstimateVO.builder()
                .totalPrize(totalPrize)
                .prizeDetails(prizeDetails)
                .build();
        
        log.info("用户{}的大乐透奖金统计结果：总奖金{}，各等级明细数量：{}", 
                userId, totalPrize, prizeDetails.size());
        return result;
    }
    
    @Override
    public RedBallHitRateVO getFrontFirstBallHitRate(Long userId) {
        log.info("开始统计用户{}的大乐透前区首球命中率", userId);
        
        // 查询用户的所有预测记录（除了"待开奖"状态的）
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId)
                .eq("predictStatus", "已开奖");
        
        List<DltPredictRecord> predictRecords = dltPredictRecordMapper.selectList(queryWrapper);
        
        // 总预测次数
        int totalCount = predictRecords.size();
        
        // 统计前区首球命中次数
        int hitCount = 0;
        
        for (DltPredictRecord record : predictRecords) {
            // 获取该预测记录对应的开奖信息
            DltDrawRecord draw = dltDrawRecordService.lambdaQuery()
                    .eq(DltDrawRecord::getDrawId, String.valueOf(record.getDrawId()))
                    .one();
            
            if (draw != null && record.getFrontendBall1() != null) {
                Integer predictedFirstBall = record.getFrontendBall1();
                List<Integer> drawnFrontBalls = Arrays.asList(
                        draw.getFrontBall1(),
                        draw.getFrontBall2(),
                        draw.getFrontBall3(),
                        draw.getFrontBall4(),
                        draw.getFrontBall5()
                );
                // 比较预测的第一个前区球是否在开奖的五个前区球中
                if (drawnFrontBalls.contains(predictedFirstBall)) {
                    hitCount++;
                }
            }
        }
        
        // 计算命中率
        double hitRate = totalCount > 0 ? (double) hitCount / totalCount * 100 : 0;
        
        RedBallHitRateVO result = RedBallHitRateVO.builder()
                .totalHitCount(hitCount)
                .totalPredictedCount(totalCount)
                .hitRate(hitRate)
                .build();
        
        log.info("用户{}的大乐透前区首球命中率统计结果：命中{}次，总计{}次，命中率{}%", 
                userId, hitCount, totalCount, String.format("%.2f", hitRate));
        
        return result;
    }
    
    @Override
    public RedBallHitRateVO getFrontBallHitRate(Long userId) {
        log.info("开始统计用户{}的大乐透前区球号命中率", userId);

        // 查询用户的所有预测记录（除了"待开奖"状态的）
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId)
                .eq("predictStatus", "已开奖");
        
        List<DltPredictRecord> predictRecords = dltPredictRecordMapper.selectList(queryWrapper);
        
        int totalHitCount = 0;
        int totalRecords = predictRecords.size();

        for (DltPredictRecord record : predictRecords) {
            // 获取该预测记录对应的开奖信息
            DltDrawRecord draw = dltDrawRecordService.lambdaQuery()
                    .eq(DltDrawRecord::getDrawId, String.valueOf(record.getDrawId()))
                    .one();
            
            if (draw != null) {
                List<Integer> predictedFrontBalls = Arrays.asList(
                        record.getFrontendBall1(),
                        record.getFrontendBall2(),
                        record.getFrontendBall3(),
                        record.getFrontendBall4(),
                        record.getFrontendBall5()
                );
                
                List<Integer> drawnFrontBalls = Arrays.asList(
                        draw.getFrontBall1(),
                        draw.getFrontBall2(),
                        draw.getFrontBall3(),
                        draw.getFrontBall4(),
                        draw.getFrontBall5()
                );

                // 计算当前记录命中的前区球数
                for (Integer predictedBall : predictedFrontBalls) {
                    if (predictedBall != null && drawnFrontBalls.contains(predictedBall)) {
                        totalHitCount++;
                    }
                }
            }
        }

        int totalPredictedCount = totalRecords * 5; // 每条记录预测5个前区球
        double hitRate = (totalPredictedCount > 0) ? ((double) totalHitCount / totalPredictedCount) * 100 : 0;
        
        RedBallHitRateVO result = RedBallHitRateVO.builder()
                .totalHitCount(totalHitCount)
                .totalPredictedCount(totalPredictedCount)
                .hitRate(hitRate)
                .build();
        
        log.info("用户{}的大乐透前区球号命中率统计结果：命中总数{}，预测总数{}，命中率{}%", 
                userId, totalHitCount, totalPredictedCount, String.format("%.2f", hitRate));
        
        return result;
    }
    
    @Override
    public RedBallHitRateVO getBackFirstBallHitRate(Long userId) {
        log.info("开始统计用户{}的大乐透后区首球命中率", userId);
        
        // 查询用户的所有预测记录（除了"待开奖"状态的）
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId)
                .eq("predictStatus", "已开奖");
        
        List<DltPredictRecord> predictRecords = dltPredictRecordMapper.selectList(queryWrapper);
        
        // 总预测次数
        int totalCount = predictRecords.size();
        
        // 统计后区首球命中次数
        int hitCount = 0;
        
        for (DltPredictRecord record : predictRecords) {
            // 获取该预测记录对应的开奖信息
            DltDrawRecord draw = dltDrawRecordService.lambdaQuery()
                    .eq(DltDrawRecord::getDrawId, String.valueOf(record.getDrawId()))
                    .one();
            
            if (draw != null && record.getBackendBall1() != null) {
                Integer predictedFirstBackBall = record.getBackendBall1();
                List<Integer> drawnBackBalls = Arrays.asList(
                        draw.getBackBall1(),
                        draw.getBackBall2()
                );
                // 比较预测的第一个后区球是否在开奖的两个后区球中
                if (drawnBackBalls.contains(predictedFirstBackBall)) {
                    hitCount++;
                }
            }
        }
        
        // 计算命中率
        double hitRate = totalCount > 0 ? (double) hitCount / totalCount * 100 : 0;
        
        RedBallHitRateVO result = RedBallHitRateVO.builder()
                .totalHitCount(hitCount)
                .totalPredictedCount(totalCount)
                .hitRate(hitRate)
                .build();
        
        log.info("用户{}的大乐透后区首球命中率统计结果：命中{}次，总计{}次，命中率{}%", 
                userId, hitCount, totalCount, String.format("%.2f", hitRate));
        
        return result;
    }
    
    @Override
    public RedBallHitRateVO getBackBallHitRate(Long userId) {
        log.info("开始统计用户{}的大乐透后区球号命中率", userId);

        // 查询用户的所有预测记录（除了"待开奖"状态的）
        QueryWrapper<DltPredictRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId)
                .eq("predictStatus", "已开奖");
        
        List<DltPredictRecord> predictRecords = dltPredictRecordMapper.selectList(queryWrapper);
        
        int totalHitCount = 0;
        int totalRecords = predictRecords.size();

        for (DltPredictRecord record : predictRecords) {
            // 获取该预测记录对应的开奖信息
            DltDrawRecord draw = dltDrawRecordService.lambdaQuery()
                    .eq(DltDrawRecord::getDrawId, String.valueOf(record.getDrawId()))
                    .one();
            
            if (draw != null) {
                List<Integer> predictedBackBalls = Arrays.asList(
                        record.getBackendBall1(),
                        record.getBackendBall2()
                );
                
                List<Integer> drawnBackBalls = Arrays.asList(
                        draw.getBackBall1(),
                        draw.getBackBall2()
                );

                // 计算当前记录命中的后区球数
                for (Integer predictedBall : predictedBackBalls) {
                    if (predictedBall != null && drawnBackBalls.contains(predictedBall)) {
                        totalHitCount++;
                    }
                }
            }
        }

        int totalPredictedCount = totalRecords * 2; // 每条记录预测2个后区球
        double hitRate = (totalPredictedCount > 0) ? ((double) totalHitCount / totalPredictedCount) * 100 : 0;
        
        RedBallHitRateVO result = RedBallHitRateVO.builder()
                .totalHitCount(totalHitCount)
                .totalPredictedCount(totalPredictedCount)
                .hitRate(hitRate)
                .build();
        
        log.info("用户{}的大乐透后区球号命中率统计结果：命中总数{}，预测总数{}，命中率{}%", 
                userId, totalHitCount, totalPredictedCount, String.format("%.2f", hitRate));
        
        return result;
    }
}
